#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/wait.h>

#define UART_VTIME 	0u 	/*单位:100ms*/
static int fd_uartx = -1;
static int _set_termios(int fd,long speed,char databit,char stopbit,char oebit, unsigned char vttime)
{  

	struct termios tty;
	struct termios *pstTtyattr= &tty;
	int err = -1;  
	memset(pstTtyattr, 0 , sizeof(struct termios));
	pstTtyattr->c_cflag |= CLOCAL | CREAD;  
	pstTtyattr->c_cflag &= ~CSIZE;  
	switch(databit)    
	{  
		case 7:	  
			pstTtyattr->c_cflag |= CS7;	  
			break;  
		case 8:	  
			pstTtyattr->c_cflag |= CS8;	  
		  break;  
		default:	  
			pstTtyattr->c_cflag |= CS8;	  
			break;    
	}  
	switch(stopbit)    
	{		
		case 1:			
			pstTtyattr->c_cflag &= ~CSTOPB;			
			break;		
		case 2:			
			pstTtyattr->c_cflag |= CSTOPB;		  
			break;		
		default:		  
			pstTtyattr->c_cflag &= ~CSTOPB;		  
			break;    
	}  
	switch(oebit)    
	{  
		case 'O':
			/* odd */	 
			pstTtyattr->c_cflag |= PARENB;	  
			pstTtyattr->c_cflag |= (INPCK | ISTRIP);	  
			pstTtyattr->c_cflag |= PARODD;	  
			break;  
		case 'E':/* even */	 
			pstTtyattr->c_cflag |= PARENB;	  
			pstTtyattr->c_cflag |= (INPCK | ISTRIP);	  
			pstTtyattr->c_cflag &= ~PARODD;	  
			break;  
		case 'N':	  
			pstTtyattr->c_cflag &= ~PARODD;	  
			break;  
		default:	  
			pstTtyattr->c_cflag &= ~PARODD;	  
			break;    
	}  
	switch(speed)    
	{  
		case 2400:	  
			cfsetispeed(pstTtyattr,B2400);	  
			cfsetospeed(pstTtyattr,B2400);	  
			break;  
		case 4800:	  
			cfsetispeed(pstTtyattr,B4800);	  
			cfsetospeed(pstTtyattr,B4800);	  
			break;  
		case 9600:	  
			cfsetispeed(pstTtyattr,B9600);	  
			cfsetospeed(pstTtyattr,B9600);	  
			break;  
		case 57600:	  
			cfsetispeed(pstTtyattr,B57600);	  
			cfsetospeed(pstTtyattr,B57600);	  
			break;  
		case 19200:	  
			cfsetispeed(pstTtyattr,B19200);	  
			cfsetospeed(pstTtyattr,B19200);	  
			break;  
		case 115200:
            /*
		    cfsetspeed(pstTtyattr,B115200);	*/
			cfsetispeed(pstTtyattr,B115200);	  
			cfsetospeed(pstTtyattr,B115200);	  
			break;  
		default:	  
			cfsetispeed(pstTtyattr,B9600);	  
			cfsetospeed(pstTtyattr,B9600);	  
			break;    
	}  
	pstTtyattr->c_cc[VTIME] = vttime;  
	pstTtyattr->c_cc[VMIN] = 0;  
	if(tcflush(fd,TCIFLUSH)!= 0)
	{
		perror("tcgetattr");
		return err;
	}
	if((tcsetattr(fd,TCSANOW,pstTtyattr)) != 0)   /* 激活新配置 */ 
	{  	
		perror("popen");
	}  
	else  
	{	   
		err = 0;  
	}  
	return err;
}

static void _hadware_close(void)
{
	if(fd_uartx >= 0){
		if(0 != close(fd_uartx))
			printf("at com close err\n");
	}
	fd_uartx = -1;
}

static void _user_sigint(int signo)  {
    _hadware_close();
    exit(0);
}
static void _pri_init(void) {
    signal(SIGINT, _user_sigint);
}

int simple_uart_init(const char* devname, int bound)
{
	int fd, ret;
    _pri_init();
	_hadware_close();
	fd = open(devname, O_RDWR|O_NOCTTY);
	if(fd < 0) {
		printf("%s open err\n", devname);
		return -1;
	}	
	ret = _set_termios(fd,bound,8,'1','N', UART_VTIME);	
	if(ret < 0) {
		printf("%s set err\n", devname);
		return -2;
	}	
	fd_uartx = fd;
	printf("%s init ok %d\n", devname, fd);
	return 0;
}

void simple_uart_send(const unsigned char *tbuf, unsigned int len)
{
	int fd = fd_uartx;
	int ret = write(fd, tbuf, len);
    if(ret < 0) {
        printf("simple uart send faild %d\n", ret);
    }
}

int simple_uart_rec(unsigned char *rbuf, unsigned int buflen)
{
	int len = 0, rlen = 0; 
	int fd = fd_uartx;
    int wait = 0;
	do{
		len = read(fd, &rbuf[rlen], (int)buflen- rlen);
        if(len < 0) {
            printf("simple uart recv faild %d\n", len);
            return len;
        }
		else if(len > 0) {
            wait = 2;
		    rlen+= len;
		}
        if(wait > 0) {
            usleep(10*1000);
        }
	}while(wait-- && rlen < (int)buflen);
	return rlen;
}

void simple_uart_close(void) {
    _hadware_close();
}

#if 0

int main(void)
{
    pri_init();
    simple_uart_init("/dev/ttyUSB0", 115200);
    while(1) {
        unsigned char buf[1024];
        int len = simple_uart_rec(buf, 1024);
        if(len > 0) {
            buf[len] = 0;
            printf("rec %d : %s\n", len, (char*)buf);
            simple_uart_send(buf, len);
        }
        usleep(1000*10);
    }
    return 0;
}

#endif




